﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using UnityEditor;
using UnityEngine;

namespace Nirvana
{
	[Serializable]

	public class ModelAnimationImportConfig
	{
		[SerializeField]
		private ModelImporterAnimationTypeVariate animationType;
#if UNITY_2019_1_OR_NEWER
		[SerializeField]
		private ModelImporterAvatarSetupVariate avatarDefinition;
#endif
		[Tooltip("从此资源导入动画,静态Mesh就不要开启导入动画功能")]
		[SerializeField]
		private BoolVariate importAnimation;


		[Tooltip("优化游戏对象，开启此项，可以优化有动画的角色的性能,这个优化会大幅节省Animatior.Update这一项的耗时")]
		[SerializeField]
		private BoolVariate optimizeGameObjects;

		[SerializeField]
		private BoolVariate bakeAnimations;

		[Tooltip("将动画曲线重新采样为四元数值，并为动画中的每个帧生成一个新的四元数关键帧。默认情况下会启用此选项。仅当原始动画中的关键点之间存在插值问题时，才应禁用此选项来保留最初创作的动画曲线。")]
		[SerializeField]
		private BoolVariate resampleCurves;

		[SerializeField]
		private ModelImporterAnimationCompressionVariate animationCompression;

		[Tooltip("旋转误差（度数）")]
		[SerializeField]
		private FloatVariate animationRotationError;
		[Tooltip("位置误差")]
		[SerializeField]
		private FloatVariate animationPositionError;
		[Tooltip("缩放误差")]
		[SerializeField]
		private FloatVariate animationScaleError;

		[Tooltip("曲线精度压缩f3")]
		[SerializeField]
		private BoolVariate floatOptimize;

        [Tooltip("剔除接近0的曲线,模型动画使用,UI动画不要清除，会清除Alpha等值的误判")]
        [SerializeField]
        private BoolVariate clearEmptyCurve;

        [Tooltip("曲线剔除scale信息")]
		[SerializeField]
		private BoolVariate scaleOptimize;

		[SerializeField]
		private ModelImporterHumanoidOversamplingVariate humanoidOversampling;

		[SerializeField]
		private StringVariate motionNodeName;

		[SerializeField]
		private ModelImporterGenerateAnimationsVariate generateAnimations;

		[SerializeField]
		private BoolVariate autoSplitAnimationClip;

		public void MatchRule(ModelImporter import)
        {
			if (this.importAnimation.IsHasValue())
			{
				import.importAnimation = this.importAnimation.GetValue();
			}
			if (this.optimizeGameObjects.IsHasValue())
			{
				import.optimizeGameObjects = this.optimizeGameObjects.GetValue();
			}
			if (this.bakeAnimations.IsHasValue()&& import.isBakeIKSupported)
			{
				import.bakeIK = this.bakeAnimations.GetValue();
			}
			if (this.resampleCurves.IsHasValue())
			{
				import.resampleCurves = this.resampleCurves.GetValue();
			}
			if (this.animationCompression.IsHasValue())
			{
				import.animationCompression = this.animationCompression.GetValue();
			}
			if (this.animationRotationError.IsHasValue())
			{
				import.animationRotationError = this.animationRotationError.GetValue();
			}
			if (this.animationPositionError.IsHasValue())
			{
				import.animationPositionError = this.animationPositionError.GetValue();
			}
			if (this.animationScaleError.IsHasValue())
			{
				import.animationScaleError = this.animationScaleError.GetValue();
			}

			if (this.animationType.IsHasValue())
			{
				import.animationType = this.animationType.GetValue();
			}
			if (this.humanoidOversampling.IsHasValue())
			{
				import.humanoidOversampling = this.humanoidOversampling.GetValue();
			}
			if (this.motionNodeName.IsHasValue())
			{
				import.motionNodeName = this.motionNodeName.GetValue();
			}
 #if UNITY_2019_1_OR_NEWER
            if (avatarDefinition.IsHasValue())
            {
				import.avatarSetup = avatarDefinition.GetValue();
			}
#endif
			//legacy动画类型有效
			//if (this.generateAnimations.IsHasValue())
			//{
			//    import.generateAnimations = this.generateAnimations.GetValue();
			//}
			//if (this.animationWrapMode.IsHasValue())
			//{
			//	import.animationWrapMode = this.animationWrapMode.GetValue();
			//}
			if (this.autoSplitAnimationClip.IsHasValue())
			{
				if(this.autoSplitAnimationClip.GetValue()) this.SplitAnimationClip(import);
			}
#if UNITY_2019_1_OR_NEWER
			import.SaveAndReimport(); //unity2019版本需要主动刷新
#endif

        }

        /// <summary>
        /// 对整体的一个动画作切割
        /// 说明：
        ///		需要提供一个FBX同名的切割文件  fbxname.split , 脚本会根据split文件对每个动画作切割
        ///		每个动画的参数格式： clipname firstframe lastframe loop
        ///		例如：待机动画 ： idle 0 70 true
        /// </summary>
        private void SplitAnimationClip(ModelImporter import)
        {
			string directoryName = Path.GetDirectoryName(import.assetPath);
			string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(import.assetPath);
			string path = Path.Combine(directoryName, fileNameWithoutExtension + ".split");
	
			if (!File.Exists(path))
			{
				return;
			}

			using (StreamReader streamReader = File.OpenText(path))
			{
				List<ModelImporterClipAnimation> list = new List<ModelImporterClipAnimation>();
				while (!streamReader.EndOfStream)
				{
					string clipInfo = streamReader.ReadLine();
					if (!string.IsNullOrEmpty(clipInfo))
					{
						string[] array = clipInfo.Split(new char[]
						{
							' ',
							'\t'
						}, StringSplitOptions.RemoveEmptyEntries);
						if (array.Length != 4)
						{
							Debug.LogWarningFormat("The animation split file {0} format error: {1}", new object[]
							{
								fileNameWithoutExtension,
								clipInfo
							});
						}
						else
						{
							string clipName = array[0];
							float firstFrame;
							float lastFrame;
							bool loopTime;
			
							if (string.IsNullOrEmpty(clipName))
							{
								Debug.LogWarningFormat("The animation split file {0} format error: {1}", new object[]
								{
									fileNameWithoutExtension,
									clipInfo
								});
							}
							else if (!float.TryParse(array[1], out firstFrame))
							{
								Debug.LogWarningFormat("The animation split file {0} format error: {1}", new object[]
								{
									fileNameWithoutExtension,
									clipInfo
								});
							}
							else if (!float.TryParse(array[2], out lastFrame))
							{
								Debug.LogWarningFormat("The animation split file {0} format error: {1}", new object[]
								{
									fileNameWithoutExtension,
									clipInfo
								});
							}
							else if (!bool.TryParse(array[3], out loopTime))
							{
								Debug.LogWarningFormat("The animation split file {0} format error: {1}", new object[]
								{
									fileNameWithoutExtension,
									clipInfo
								});
							}
							else
							{
								list.Add(new ModelImporterClipAnimation
								{
									name = clipName,
									firstFrame = firstFrame,
									lastFrame = lastFrame,
									loopTime = loopTime,
								});
							}
						}
					}
				}
				import.clipAnimations = list.ToArray();
			}
		}

		/// <summary>
		/// 精度压缩
		/// </summary>
		/// <param name="theAnimation"></param>
		public void AnimationClipOptimize(AnimationClip theAnimation)
        {
            //去除scale曲线
            if (scaleOptimize.IsHasValue() && scaleOptimize.GetValue())
            {
				foreach (EditorCurveBinding theCurveBinding in AnimationUtility.GetCurveBindings(theAnimation))
				{
					string name = theCurveBinding.propertyName.ToLower();
					if (name.Contains("scale"))
					{
						AnimationUtility.SetEditorCurve(theAnimation, theCurveBinding, null);
					}
				}
			}
			//浮点数精度压缩到f3
			if (floatOptimize.IsHasValue() && floatOptimize.GetValue())
            {
				EditorCurveBinding[] curveBindings = AnimationUtility.GetCurveBindings(theAnimation);
				Keyframe keyframe;
				Keyframe[] keyFrames;
				foreach (var curveBinding in curveBindings)
				{
					AnimationCurve animationCurve = AnimationUtility.GetEditorCurve(theAnimation, curveBinding);
					if (animationCurve == null || animationCurve.keys == null)
					{
						continue;
					}
					// 要移除的帧
					List<int> removeIdxs = new List<int>();
					keyFrames = animationCurve.keys;
					for (int i = 0; i < keyFrames.Length; i++)
					{
						keyframe = keyFrames[i];
						keyframe.value = float.Parse(keyframe.value.ToString("f3"));
						keyframe.inTangent = float.Parse(keyframe.inTangent.ToString("f3"));
						keyframe.outTangent = float.Parse(keyframe.outTangent.ToString("f3"));
						keyframe.inWeight = float.Parse(keyframe.inWeight.ToString("f3"));
						keyframe.outWeight = float.Parse(keyframe.outWeight.ToString("f3"));
						keyFrames[i] = keyframe;
                        if (clearEmptyCurve.IsHasValue() && clearEmptyCurve.GetValue())
                        {
                            //恒量 (变化小的关键帧) 比较曲线的输入和输出变化，如果是基本稳定，即为常量
                            // 是否是异常量关键帧或者无限接近0
                            if ((float.IsInfinity(keyframe.inTangent) && float.IsInfinity(keyframe.outTangent))
                            || (Mathf.Abs(keyframe.inTangent) <= float.Epsilon && Mathf.Abs(keyframe.outTangent) <= float.Epsilon))
                            {
                                removeIdxs.Add(i);
                            }
                        }
  
					}
					animationCurve.keys = keyFrames;
					//AnimationUtility.SetEditorCurve(theAnimation, curveBinding, animationCurve); //不要使用此接口，会增大文件大小。负优化了。
					//theAnimation.SetCurve(curveBinding.path, curveBinding.type, curveBinding.propertyName, animationCurve);

					// 移除
					for (int r = removeIdxs.Count - 1; r >= 0; --r)
					{
						animationCurve.RemoveKey(removeIdxs[r]);
					}
					// 如果curve的关键帧已经没有了，直接移除空的curve
					if (animationCurve.length == 0)
					{
						AnimationUtility.SetEditorCurve(theAnimation, curveBinding, null);
					}
					else
					{
						theAnimation.SetCurve(curveBinding.path, curveBinding.type, curveBinding.propertyName, animationCurve);
					}
				}
			}
		}

	}
}

